/**
 * ThumbnailGridMediator is responsible for managing the ThumbnailGrid
 * component including paginating, displaying banner ads and 
 * dispatching brochure select events when a thumbnail is pressed.
 * 
 * @author		Scott Steven Rodriguez
 * @link 		http://www.flashsherpa.com
 */
package com.ettractions.kiosk.mediators
{
	import com.ettractions.kiosk.components.ThumbnailGrid;
	import com.ettractions.kiosk.components.ThumbnailGridPage;
	import com.ettractions.kiosk.events.BrochureSelectedEvent;
	import com.ettractions.kiosk.events.SelectBrochureEvent;
	import com.ettractions.kiosk.events.ThumbnailGridEvent;
	import com.ettractions.kiosk.events.ViewStateEvent;
	import com.ettractions.kiosk.models.KioskModel;
	import com.ettractions.kiosk.utils.ViewUtils;
	import com.ettractions.kiosk.vo.BrochureVO;
	import com.greensock.TweenLite;
	import com.greensock.easing.Expo;
	
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	import mx.events.FlexEvent;
	
	import org.robotlegs.mvcs.Mediator;
	
	import spark.components.List;
	import spark.events.IndexChangeEvent;
	
	public class ThumbnailGridMediator extends Mediator
	{
		private static const WITH_AD_LIST_ITEM_COUNT:uint = 35;
		
		private static const WITH_AD_LIST_WIDTH:uint = 1005;		
		
		private static const WITHOUT_AD_LIST_ITEM_COUNT:uint = 40;
		
		private static const WITHOUT_AD_LIST_WIDTH:uint = 1150;		
		
		private static const TWEEN_DURATION:Number = 1;
		
		private static const TWEEN_EQUATION:Function = Expo.easeOut;

		private static const IDLING_PAGE_CHANGE_DELAY:uint = 10000;
		
		[Inject]
		public var model:KioskModel;
		
		[Inject]
		public var view:ThumbnailGrid;
		
		private var _newPage:ThumbnailGridPage;
		
		private var _oldPageTween:TweenLite;		
		
		private var _newPageTween:TweenLite;
		
		private var _pageChangeTimer:Timer = new Timer(IDLING_PAGE_CHANGE_DELAY, 1);
		
		private var _currentFirstListItemIndex:int = 0;
		
		private var _currentPageIndex:int = 0;
		
		private var _currentAdIndex:int = -1;
		
		override public function onRegister():void
		{
			eventDispatcher.addEventListener(ViewStateEvent.PRE_RENDERING_COMPLETE, handlePreRenderingComplete);		
			eventDispatcher.addEventListener(ViewStateEvent.IDLING, handleIdling);
			eventDispatcher.addEventListener(BrochureSelectedEvent.BROCHURE_SELECTED, handleBrochureSelected);
			
			view.previousButton.addEventListener(MouseEvent.CLICK, handleButtonClick);
			
			view.nextButton.addEventListener(MouseEvent.CLICK, handleButtonClick);
			
			_pageChangeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, handlePageChangeTimerComplete);
		}
		
		/**
		 * Ad display logic can be worked out here; currently just toggling
		 * ads on and off between pages and cycling through the ads
		 */
		private function determineAdIndex(pageIndex:int):int
		{
			if ((pageIndex % 2) != 0)
				return -1;
			
			if (++_currentAdIndex == model.ads.length)
				_currentAdIndex = 0;
			
			return _currentAdIndex;
		}
		
		private function populatePage(page:ThumbnailGridPage, firstListItemIndex:int, adIndex:int):ThumbnailGridPage
		{
			var itemCount:uint = adIndex > -1
			                   ? WITH_AD_LIST_ITEM_COUNT
			                   : WITHOUT_AD_LIST_ITEM_COUNT;
			var listWidth:uint = adIndex > -1
			                   ? WITH_AD_LIST_WIDTH
			                   : WITHOUT_AD_LIST_WIDTH;
			
			page.list.width = listWidth;
			page.list.addEventListener(FlexEvent.UPDATE_COMPLETE, handleListUpdateComplete, false, 0, true);
			page.list.dataProvider = ViewUtils.generateListDataProvider(model.condensedBrochures, itemCount, firstListItemIndex);
			
			page.ad.visible = adIndex > -1;
			
			if (page.ad.visible)
				page.ad.source = model.ads[adIndex].image
			
			eventDispatcher.dispatchEvent(new ThumbnailGridEvent(ThumbnailGridEvent.GRID_PAGE_CHANGING));
			
			return page;
		}
		
		private function animateToNewPage(direction:int = 1):void
		{
			var adIndex:int;
			var itemCount:uint;
			var oldPageDestX:int;
			
			_currentPageIndex += direction;
			
			adIndex = determineAdIndex(_currentPageIndex);
			itemCount = adIndex > -1
				? WITH_AD_LIST_ITEM_COUNT
				: WITHOUT_AD_LIST_ITEM_COUNT;
			
			_newPage = ThumbnailGridPage(view.addElement((new ThumbnailGridPage())));
			
			switch (direction)
			{
				case 1:
					_currentFirstListItemIndex += itemCount;
					_newPage.x = view.width;
					oldPageDestX = -view.width;
					break;				
				
				case -1:
					_currentFirstListItemIndex -= itemCount;
					_newPage.x = -view.width;
					oldPageDestX = view.width;
					break;
			}
			
			if (_currentFirstListItemIndex < 0)
				_currentFirstListItemIndex = model.condensedBrochures.length + _currentFirstListItemIndex;
				
			else if (_currentFirstListItemIndex >= model.condensedBrochures.length)
				_currentFirstListItemIndex = _currentFirstListItemIndex - model.condensedBrochures.length;
			
			populatePage(_newPage, _currentFirstListItemIndex, adIndex);
			
			view.previousButton.visible = view.nextButton.visible = false;
			
			_oldPageTween = new TweenLite(
				view.page,
				TWEEN_DURATION,
				{
					x:oldPageDestX,
					ease:TWEEN_EQUATION
				}
			);
			
			_newPageTween = new TweenLite(
				_newPage,
				TWEEN_DURATION,
				{
					x:0,
					ease:TWEEN_EQUATION,
					onComplete:handleTweenComplete
				}
			);
			
			_oldPageTween.play();
			_newPageTween.play();
		}
		
		private function handlePreRenderingComplete(event:ViewStateEvent):void
		{
			eventDispatcher.removeEventListener(ViewStateEvent.PRE_RENDERING_COMPLETE, handlePreRenderingComplete);
			
			populatePage(view.page, _currentFirstListItemIndex, determineAdIndex(_currentPageIndex));
			
			view.page.list.addEventListener(IndexChangeEvent.CHANGE, handleListIndexChange);
		}
		
		private function handleIdling(event:ViewStateEvent):void
		{
			_pageChangeTimer.reset();
			_pageChangeTimer.start();
			
			eventDispatcher.addEventListener(ViewStateEvent.USER_INTERACTION, handleUserInteraction);
		}
		
		private function handleUserInteraction(event:ViewStateEvent):void
		{
			eventDispatcher.removeEventListener(ViewStateEvent.USER_INTERACTION, handleUserInteraction);
			
			_pageChangeTimer.stop();
		}
		
		private function handleBrochureSelected(event:BrochureSelectedEvent):void
		{
			if (event.brochure == null)
			{
				view.visible = true;
	
				populatePage(view.page, _currentFirstListItemIndex, determineAdIndex(_currentPageIndex));
			}
			
			else
			{
				view.visible = false;
				
				if (_oldPageTween)
					_oldPageTween.complete(false, true);
				
				if (_newPageTween)
					_newPageTween.complete(false, true);
				
				if (_newPage)
				{
					view.removeElement(_newPage);
					
					_newPage = null;
				}
				
				view.page.x = 0;
			}
		}
		
		private function handleListUpdateComplete(event:FlexEvent):void
		{
			var list:List = List(event.target);
			
			list.removeEventListener(FlexEvent.UPDATE_COMPLETE, handleListUpdateComplete);
			
			if (!_newPage)
				eventDispatcher.dispatchEvent(new ThumbnailGridEvent(ThumbnailGridEvent.GRID_PAGE_CHANGED));
			
			else
				list.addEventListener(IndexChangeEvent.CHANGE, handleListIndexChange);
		}
		
		private function handleListIndexChange(event:IndexChangeEvent):void
		{
			var list:List = List(event.target);
			
			eventDispatcher.dispatchEvent(new SelectBrochureEvent(SelectBrochureEvent.SELECT_BROCHURE, BrochureVO(list.dataProvider.getItemAt(event.newIndex))));
			
			list.selectedIndex = -1;
		}
		
		private function handleButtonClick(event:MouseEvent):void
		{
			switch (event.target)
			{
				case view.nextButton:
					animateToNewPage(1);
					break;				
				
				case view.previousButton:
					animateToNewPage(-1);
					break;
			}
		}
		
		private function handlePageChangeTimerComplete(event:TimerEvent):void
		{
			animateToNewPage(1);
			
			_pageChangeTimer.reset();
			_pageChangeTimer.start();
		}
		
		private function handleTweenComplete():void
		{
			view.page.list.removeEventListener(IndexChangeEvent.CHANGE, handleListIndexChange);
			
			view.removeElement(view.page);
			
			view.page = _newPage;
			view.page.list.addEventListener(IndexChangeEvent.CHANGE, handleListIndexChange);
			
			_newPage = null;
			
			_oldPageTween = _newPageTween = null;
			
			view.previousButton.visible = view.nextButton.visible = true;
			
			eventDispatcher.dispatchEvent(new ThumbnailGridEvent(ThumbnailGridEvent.GRID_PAGE_CHANGED));
		}
	}
}